﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;
using System.Threading;

namespace PerfAnalyzerLib
{
	public class FileParser : IDisposable
	{
		// TODO: comment
		private FileInfo _fileInfo;
		private Queue<string> _linesQueue;
		private const int QueueSize = 1000;
		private volatile bool _continueParsing = true;
		private volatile bool _endOfFileReached = false;
		private object myLock = new object();

		/// <summary>
		/// Constructor.
		/// </summary>
		/// <param name="filename">Filename to parse.</param>
		public FileParser(string filename)
		{
			_linesQueue = new Queue<string>(QueueSize);

			if (!File.Exists(filename))
			{
				throw new FileNotFoundException("Cannot find the file " + filename, filename);
			}

			_fileInfo = new FileInfo(filename);

			Thread workerThread = new Thread(this.Parse);
			workerThread.Start();
		}

		/// <summary>
		/// Finaliser
		/// </summary>
		~FileParser()
		{
			Dispose();
		}

		/// <summary>
		/// Get the next line from the file being read.
		/// </summary>
		/// <returns>The next line, null if the end of file as been reached.</returns>
		public string GetLine()
		{
			if (!_continueParsing)
			{
				return null;
			}

			while (0 == _linesQueue.Count && !_endOfFileReached)
			{
				Thread.Sleep(100);
			}

			if (0 == _linesQueue.Count && _endOfFileReached)
			{
				return null;
			}

			lock (myLock)
			{
				return _linesQueue.Dequeue();
			}
		}

		/// <summary>
		/// Parse the the file and put the data in a queue.
		/// </summary>
		private void Parse()
		{
			using (var sr = new StreamReader(File.OpenRead(_fileInfo.FullName)))
			{
				string line;
				while (_continueParsing && (line = sr.ReadLine()) != null)
				{
					lock (myLock)
					{
						_linesQueue.Enqueue(line);
					}

					// if queue is full, wait before contuing further.
					while (_continueParsing && _linesQueue.Count >= QueueSize)
					{
						Thread.Sleep(500);
					}
				}
			}

			_endOfFileReached = true;
		}

		// Stop parsing.
		public void StopParsing()
		{
			_continueParsing = false;
		}

		/// <summary>
		/// Dispose of the stream.
		/// </summary>
		public void Dispose()
		{
			_continueParsing = false;
		}
	}
}
